#include "lora_service.h"
#include "circular_buffer.h"
#include "lx_serial.h"
#include "crc.h"
#include <stdint.h>
#include <termios.h>
#include <stdio.h>
#include <time.h>
#include <sys/select.h>  // 提供 fd_set 和 select() 函数
#include <sys/time.h>    // 提供 struct timeval
#include <stdarg.h>
#include <libubus.h>
#include <libubox/uloop.h>
#include <libubox/list.h>
#include <libubox/blobmsg_json.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "power_utils.h"
#include "frame_util.h"
#include "data_type.h"
#include "redis_util.h"
#include "hash_map.h"

#define         DEBUG               1
#define         LORA_DEV            "/dev/ttyS2"

//发送的帧类型
#define           CMD_CTL_WAKE                      0x01//控制设备电源
#define           CMD_CTL_SLEEP                     0x02//控制设备电源

#define RX_BUF_SIZE 256            // 读取缓冲区大小
#define TIMEOUT_MS  300
#define FRAME_TERMINATOR 0xA3      // 数据帧结束字符
union float_u32_converter {
    uint32_t u32;
    float f;
};

extern pShartData ubus_cmd_Psd;
extern HashMap *online_devs;

static int LoRaFD = -1;//串口1的文件描述符
uint8_t curMsgRandom = 0x00; //消息编号，用于判断消息是否是已接收过的消息

// 更新运行时长（需在1ms定时器中断中调用）
RuntimeCounter *RuntimeCounter_Update(uint32_t run_sec) {
    RuntimeCounter *runtime = (RuntimeCounter *)malloc(sizeof(RuntimeCounter));
    runtime->days = run_sec / (24 * 60 * 60);
    runtime->hours = (run_sec % (24 * 60 * 60)) / (60 * 60);
    runtime->minutes = (run_sec % (60 * 60)) / 60;
    runtime->seconds = run_sec % 60;
    return runtime;
}

void lora_send(uint8_t *data, int size)
{

    // uint8_t *res = NULL;
    // uint16_t res_len = encode_frame(data, size, &res);

    printf("send: ");
    for (size_t i = 0; i < size; i++)
    {
        printf("%02X ", *(data+i));
    }
    printf("\n");
    lx_serial_write(LoRaFD, data, size);
    // free(res);
}
void lora_printf(const char *format, ...)
{
    char buffer[256]={'\0'};
    va_list args;
    va_start(args, format);
    int len = vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    printf("lora_printf:%s, len: %d\n", buffer, len);
    lx_serial_write(LoRaFD, buffer, len);
}

/**
 * 日志解析
 */
void log_parse(char val){
    switch (val)
    {
    case 0x00:
        system("echo \"$(date +'%Y-%m-%d %H:%M:%S'): heart timeout\" >> /root/energy_log.log");
        break;
    case 0x01:
        system("echo \"$(date +'%Y-%m-%d %H:%M:%S'): ding shi duan dian\" >> /root/energy_log.log");
        break;
    case 0x02:
        system("echo \"$(date +'%Y-%m-%d %H:%M:%S'): shou dong duan dian\" >> /root/energy_log.log");
        break;
    default:
        break;
    }
}

typedef enum {
    WAIT_HEADER,
    WAIT_LENGTH,
    WAIT_DATA,
    WAIT_CRC,
    WAIT_FOOTER
} ParserState;

struct blob_buf energy_buf;

void process_packet(uint8_t *buffer, uint16_t expected_length){
    printf("revice len:%d\n", expected_length);
}
void parse_data(uint8_t byte) {
    static ParserState state = WAIT_HEADER;
    static uint8_t buffer[1024];
    static size_t index = 0;
    static uint16_t expected_length = 0;

    switch (state) {
        case WAIT_HEADER:
            if (byte == 0xA6) {
                state = WAIT_LENGTH;
            }
            break;

        case WAIT_LENGTH:
            expected_length = byte;
            index = 0;
            state = WAIT_DATA;
            break;

        case WAIT_DATA:
            buffer[index++] = byte;
            if (index >= expected_length) {
                state = WAIT_CRC;
            }
            break;

        case WAIT_CRC:
            // 校验逻辑（略）
            state = WAIT_FOOTER;
            break;

        case WAIT_FOOTER:
            if (byte == 0xA3) {
                process_packet(buffer, expected_length);  // 处理完整数据包
            }
            state = WAIT_HEADER;  // 重置状态机
            break;
    }
}
void print_frame(const ProtocolFrame *frame) {
    printf("Frame: head=0x%02X, type=0x%02X, len=%d, data=[", 
           frame->head, frame->type, frame->len);
    for (int i = 0; i < frame->len; i++) {
        printf("%02X ", frame->data[i]);
    }
    printf("], crc=0x%04X\n", frame->crc);
}

/**
 * 调用MQTT服务电量信息上传服务
 */
int ubus_invoke_mqtt_energy_info(HeartData *heart) {


    // 连接 ubus
    struct ubus_context *ctx = ubus_connect(NULL);
    if (!ctx) {
        fprintf(stderr, "Failed to connect to ubus\n");
        return -1;
    }
    // 查找 network.device 的 ID
    uint32_t obj_id;
    if (ubus_lookup_id(ctx, "sihan.mqtt", &obj_id) != 0) {
        fprintf(stderr, "Failed to lookup sihan.mqtt\n");
        ubus_free(ctx);
        return -1;
    }

    blob_buf_init(&energy_buf, 0);
    blobmsg_add_u32(&energy_buf, "addr", heart->addr);
    blobmsg_add_u32(&energy_buf, "group_addr", heart->group_addr);
    blobmsg_add_u32(&energy_buf, "trans_addr", heart->trans_addr);
    blobmsg_add_u32(&energy_buf, "status", heart->status);
    union float_u32_converter converter;
    converter.f = heart->batteryVoltage;
    blobmsg_add_u32(&energy_buf, "batteryVoltage", converter.u32);
    converter.f = heart->batteryElectric;
    blobmsg_add_u32(&energy_buf, "batteryElectric", converter.u32);
    blobmsg_add_u32(&energy_buf, "batteryCapacity", heart->batteryCapacity);
    blobmsg_add_u32(&energy_buf, "batteryStatus", heart->batteryStatus);
    converter.f = heart->loadVoltage;
    blobmsg_add_u32(&energy_buf, "loadVoltage", converter.u32);
    converter.f = heart->loadElectric;
    blobmsg_add_u32(&energy_buf, "loadElectric", converter.u32);
    converter.f = heart->loadPower;
    blobmsg_add_u32(&energy_buf, "loadPower", converter.u32);
    blobmsg_add_u32(&energy_buf, "loadStatus", heart->loadStatus);
    converter.f = heart->columnVoltage;
    blobmsg_add_u32(&energy_buf, "columnVoltage", converter.u32);
    blobmsg_add_u32(&energy_buf, "columnStatus", heart->columnStatus);
    blobmsg_add_u32(&energy_buf, "runDay", heart->runDay);
    blobmsg_add_u32(&energy_buf, "lowVolCnt", heart->lowVolCnt);
    blobmsg_add_u32(&energy_buf, "todayDischarge", heart->todayDischarge);
    blobmsg_add_u32(&energy_buf, "yesterdayDischarge", heart->yesterdayDischarge);
    blobmsg_add_u32(&energy_buf, "totalDischarge", heart->totalDischarge);
    blobmsg_add_u32(&energy_buf, "todayCharge", heart->todayCharge);
    blobmsg_add_u32(&energy_buf, "yesterdayCharge", heart->yesterdayCharge);
    blobmsg_add_u32(&energy_buf, "totalCharge", heart->totalCharge);
    converter.f = heart->fDevTemperature;
    blobmsg_add_u32(&energy_buf, "fDevTemperature", converter.u32);
    converter.f = heart->fBatTemperature;
    blobmsg_add_u32(&energy_buf, "fBatTemperature", converter.u32);
    // 发起异步调用
    int ret = ubus_invoke(ctx, obj_id, "energy_info", energy_buf.head, NULL, 0, 3000);
    if (ret == 0) {
        
    }
    // 清理资源
    blob_buf_free(&energy_buf);
    ubus_free(ctx);
    return 0;
}
/**
 * 心跳解析
 */
bool heart_parse(const t_FrameData *frame){
    HeartData heart;
    heart.addr = frame->data[0] << 8 | frame->data[1];
    heart.group_addr = frame->data[2] << 8 | frame->data[3];
    heart.trans_addr = frame->data[4] << 8 | frame->data[5];
    heart.status = frame->data[6];

    // heart.offTime = frame->data[5] << 8 | frame->data[6];
    // heart.onTime = frame->data[7] << 8 | frame->data[8];

    heart.batteryVoltage = (float)((frame->data[7]<<8) + frame->data[8])/100;//电池电压
    heart.batteryElectric = (float)((frame->data[9]<<8) + frame->data[10])/1000;//电池电流
    heart.batteryCapacity =  frame->data[12];//电池余量
	heart.batteryStatus = frame->data[14];//电池状态

	heart.loadVoltage = (float)((frame->data[15]<<8) + frame->data[16])/100;//负载电压
	heart.loadElectric = (float)((frame->data[17]<<8) + frame->data[18])/1000;//负载电流
	heart.loadPower = (float)((frame->data[19]<<8) + frame->data[20]);//负载功率
	heart.loadStatus = frame->data[22];//负载状态

	heart.columnVoltage = (float)((frame->data[23]<<8) + frame->data[24])/100;//阵列电压
	heart.columnStatus = frame->data[28];//阵列状态

	heart.runDay = (frame->data[29]<<8) + frame->data[30];//运行天数
	heart.lowVolCnt = (frame->data[31]<<8) + frame->data[32];//欠压次数
	heart.todayDischarge = (frame->data[33]<<8) +frame->data[34];//今日总放电量
	heart.yesterdayDischarge = (frame->data[35]<<8) + frame->data[36];//昨日总放电量
	heart.totalDischarge = ((frame->data[37]<<24)&0xFF000000) + ((frame->data[38]<<16)&0xFF0000) + ((frame->data[39]<<8)&0xFF00) + (frame->data[40]&0xFF);//累计总放电量
	heart.todayCharge = (frame->data[41]<<8) + frame->data[42];//今日总充电量
	heart.yesterdayCharge = (frame->data[43]<<8) + frame->data[44];//昨日总充电量
	heart.totalCharge = ((frame->data[45]<<24)&0xFF000000) + ((frame->data[46]<<16)&0xFF0000) + ((frame->data[47]<<8)&0xFF00) + (frame->data[48]&0xFF);//累计总充电量
	heart.fDevTemperature = (float)((frame->data[49]<<8) + frame->data[50])/10;//控制器内部温度
	heart.fBatTemperature = (float)((frame->data[51]<<8) + frame->data[52])/10;//控制器外部温度
    time_t seconds = time(NULL);

    printf("设备地址:%04X\n组播地址:%04X\n透传地址:%04X\n设备状态:%d\n电池电压:%.2f\n电池电流:%.2f\n电池容量:%d\n电池状态:%d\n负载电压:%.2f\n负载电流:%.2f\n负载功率:%.2f\n负载状态:%d\n正列电压:%.2f\n",
    heart.addr, heart.group_addr, heart.trans_addr, heart.status,(double)heart.batteryVoltage,(double)heart.batteryElectric,heart.batteryCapacity,
    heart.batteryStatus,(double)heart.loadVoltage,(double)heart.loadElectric,(double)heart.loadPower,heart.loadStatus,(double)heart.columnVoltage);
    printf("正列状态:%d\n运行天数:%d\n欠压次数:%d\n今日放电数量:%d\n昨日放电数量:%d\n总放电数量:%d\n今日充电数量:%d\n昨日充电数量:%d\n总充电数量:%d\n设备温度:%.2f\n电池温度:%.2f\n",
    heart.columnStatus,heart.runDay,heart.lowVolCnt,heart.todayDischarge,heart.yesterdayDischarge,heart.totalDischarge,
    heart.todayCharge,heart.yesterdayCharge,heart.totalCharge,(double)heart.fDevTemperature,(double)heart.fBatTemperature);
    //如果是中心站，调用MQTT发送数据到服务器
    if(runCfg.is_center){
        ubus_invoke_mqtt_energy_info(&heart);
    }
    uint8_t num[4];
    sprintf(num, "%04X", heart.addr);
    uint8_t *str_redis = malloc(128);
    sprintf(str_redis, "+HEART:%04X,%04X,%04X,%d,%.2f,%.2f,%d,%d,%.2f,%.2f,%.2f,%d,%.2f,%d,%d,%d,%d,%d,%d,%d,%d,%d,%.2f,%.2f,%ld",
        heart.addr,heart.group_addr,heart.trans_addr,heart.status,(double)heart.batteryVoltage,(double)heart.batteryElectric,heart.batteryCapacity,
        heart.batteryStatus,(double)heart.loadVoltage,(double)heart.loadElectric,(double)heart.loadPower,heart.loadStatus,(double)heart.columnVoltage,
        heart.columnStatus,heart.runDay,heart.lowVolCnt,heart.todayDischarge,heart.yesterdayDischarge,heart.totalDischarge,
        heart.todayCharge,heart.yesterdayCharge,heart.totalCharge,(double)heart.fDevTemperature,(double)heart.fBatTemperature,seconds);
    
    map_put(online_devs, num, str_redis, str_free);

    // redis_push_data("devlist",num, str_redis); //把数据存放到redis中
    //free(str_redis);
    return true;
}
void handle_frame(t_FrameData *frame) {
    if(frame->start == 0xA6){
        switch (frame->type)
        {
        case 0x04://电源系统信息
            heart_parse(frame);
            break;
        case 0x07:
            log_parse(frame->data[0]);
            break;
        case 0x06:
        case 0x62:
        case 0x64:
        case 0x0C:
        case 0x6E:
        case 0x6C:
        case 0x66:
        case 0x70:
            pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
            memset(ubus_cmd_Psd.data, 0, 128);
            memcpy(ubus_cmd_Psd.data, frame->data, frame->len);
            ubus_cmd_Psd.len = frame->len;
            pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
            sem_post(&ubus_cmd_Psd.sem);
            break;
        }
    }
}
int open_uart(const char *uart, const int speed){
    int fd = open(uart, O_RDWR | O_NOCTTY | O_NDELAY);
    
    if (fd == -1) {
        perror("open_port: Unable to open serial port");
        return 1;
    }

    // 配置串口参数
    struct termios options;
    tcgetattr(fd, &options);
    switch (speed)
    {
    case 9600:
        cfsetispeed(&options, B9600);
        cfsetospeed(&options, B9600);
        break;
    case 115200:
        cfsetispeed(&options, B115200);
        cfsetospeed(&options, B115200);
        break;
    default:
        break;
    }
    
    
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;      // 无奇偶校验
    options.c_cflag &= ~CSTOPB;      // 1个停止位
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;          // 8数据位
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始模式
    options.c_iflag &= ~(IXON | IXOFF | IXANY); // 禁用软件流控
    options.c_iflag &= ~(ICRNL | INLCR | IGNCR); // 禁用回车换行转换
    options.c_oflag &= ~OPOST;       // 原始输出
    
    // 关键配置：非阻塞模式 + 超时控制
    options.c_cc[VMIN] = 0;          // 最小读取字节数：0
    options.c_cc[VTIME] = 0;         // 立即返回
    
    if (tcsetattr(fd, TCSANOW, &options) != 0) {
        perror("tcsetattr failed");
        close(fd);
        return 1;
    }
    
    // 设置为非阻塞模式
    fcntl(fd, F_SETFL, O_NONBLOCK);
    return fd;
}
void *uart_rev(void){
    unsigned char buffer[RX_BUF_SIZE];
    ssize_t total_read = 0;
    struct timeval timeout;
    fd_set readfds;
    printf("Waiting for data...\n");
    
    while (1) {
        FD_ZERO(&readfds);
        FD_SET(LoRaFD, &readfds);
        
        // 设置超时
        timeout.tv_sec = 0;
        timeout.tv_usec = TIMEOUT_MS * 1000;
        
        // 使用select等待数据
        int ret = select(LoRaFD + 1, &readfds, NULL, NULL, &timeout);
        
        if (ret < 0) {
            perror("select error");
            break;
        } else if (ret == 0) {
            // 超时：检查是否有数据需要处理
            if (total_read > 0) {
                printf("Received complete packet (%zd bytes): ", total_read);
                for (int i = 0; i < total_read; i++) {
                    printf("%02X ", buffer[i]);
                }
                printf("\n");

                t_FrameData *frame = parse_frame(buffer, total_read);
                if(frame) {
                    handle_frame(frame);
                    free(frame);
                }
                total_read = 0; // 重置缓冲区
            }
            continue;
        }
        
        // 有数据可读
        if (FD_ISSET(LoRaFD, &readfds)) {
            ssize_t n = read(LoRaFD, buffer + total_read, RX_BUF_SIZE - total_read);
            
            if (n > 0) {
                total_read += n;
                printf("Received %zd bytes (total: %zd)\n", n, total_read);
                
                // 检查缓冲区是否已满
                if (total_read >= RX_BUF_SIZE) {
                    printf("Buffer full! Processing data...\n");
                    total_read = 0;
                }
            } else if (n < 0 && errno != EAGAIN) {
                perror("read error");
                break;
            }
        }
    }
    close(LoRaFD);
}

void *lora_process_worker(void *param)
{
    uint8_t rx_raw_buf[RX_BUF_SIZE];
    RingBuffer rx_ring;
    ring_init(&rx_ring, rx_raw_buf, RX_BUF_SIZE);

    ProtocolParser parser;
    parser_init(&parser);

    while (1) {
        uint8_t temp_buf[128];
        int n = read(LoRaFD, temp_buf, sizeof(temp_buf));
        if (n > 0) {
            // 存入环形缓冲区
            printf("Rev %d: ", n);
            for (int i = 0; i < n; i++) {
                printf("%02X ", temp_buf[i]);
                ring_push(&rx_ring, temp_buf[i]);
            }
            printf("\n");
            // 尝试解析完整帧
            uint8_t byte;
            while (ring_pop(&rx_ring, &byte)) {
                if (parser_process_byte(&parser, byte)) {
                    print_frame(&parser.frame);
                    if(parser.frame.head == 0xA6){
                        switch (parser.frame.type)
                        {
                        case 0x04://电源系统信息
                            heart_parse(&parser.frame);
                            break;
                        case 0x07:
                            log_parse(parser.frame.data[0]);
                            break;
                        case 0x06:
                        case 0x62:
                        case 0x64:
                        case 0x0C:
                        case 0x6E:
                        case 0x6C:
                        case 0x66:
                        case 0x70:
                            pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
                            memset(ubus_cmd_Psd.data, 0, 128);
                            memcpy(ubus_cmd_Psd.data, parser.frame.data, parser.frame.len);
                            ubus_cmd_Psd.len = parser.frame.len;
                            pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
                            sem_post(&ubus_cmd_Psd.sem);
                            break;
                        }
                    }
                }
            }
        }
    }
}
void *dog_worker(void *param)
{
    while (1)
    {
        uint8_t tx_buf[7];
        int tx_len = protocol_encode(0xA5, 0x07, NULL, 0, tx_buf);
        printf("Send %d:", tx_len);
        for (size_t i = 0; i < tx_len; i++)
        {
            printf("%02X ", tx_buf[i]);
        }
        printf("\n");
        
        lx_serial_write(LoRaFD, tx_buf, tx_len);
        sleep(4 * 60 + 9);
    }
}
void lora_worker_start(void)
{
    // LoRaFD = lx_serial_open(runCfg.device, runCfg.speed);
    LoRaFD = open_uart(runCfg.device, runCfg.speed);
    if (LoRaFD == -1) {
        return;
    }
    pthread_t pid2, pdog;
    pthread_create(&pid2, NULL, (void *)uart_rev, NULL);
    // pthread_create(&pid2, NULL, (void *)lora_process_worker, NULL);
    pthread_create(&pdog, NULL, (void *)dog_worker, NULL);
}
